package com.itc.dispatch.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itc.common.core.constant.CacheConstants;
import com.itc.common.core.domain.R;
import com.itc.common.core.utils.OkHttpUtil;
import com.itc.common.redis.service.RedisService;
import com.itc.dispatch.domain.FlightDevice;
import com.itc.dispatch.domain.dto.FlightDevicePageDto;
import com.itc.dispatch.service.FlightDeviceService;
import com.itc.dispatch.mapper.FlightDeviceMapper;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import org.apache.commons.collections4.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.net.ssl.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
* @author 91516
* @description 针对表【flight_device(机位设备信息表)】的数据库操作Service实现
* @createDate 2024-08-19 16:46:03
*/
@Service
public class FlightDeviceServiceImpl extends ServiceImpl<FlightDeviceMapper, FlightDevice>
    implements FlightDeviceService{

    @Resource
    private RedisService redisService;
    private String videoUserName = "ythzdykdj";
    private String videoUserPassword = "Ythzdykdj@123";
    private String loginUrl = "https://10.48.221.66:18531/loginInfo/login/v1.0";
    private String getVideoUrl = "https://10.48.221.66:18531/video/rtspurl/v1.0";
    private String urlAddress = "http://10.81.41.214/videoUrl/get/flv/hls/stream?url=";

    @Override
    public R<List<FlightDevice>> getList(FlightDevice flightDevice) {
        LambdaQueryWrapper<FlightDevice> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(flightDevice.getDeviceName()),FlightDevice::getDeviceName,flightDevice.getDeviceName());
        wrapper.like(StringUtils.isNotBlank(flightDevice.getDevicePosition()),FlightDevice::getDevicePosition,flightDevice.getDevicePosition());
        wrapper.like(StringUtils.isNotBlank(flightDevice.getDeviceCode()),FlightDevice::getDeviceCode,flightDevice.getDeviceCode());
        wrapper.like(flightDevice.getPositionType() != null,FlightDevice::getPositionType,flightDevice.getPositionType());
        wrapper.eq(FlightDevice::getDelete,0);
        List<FlightDevice> flightDevices = this.baseMapper.selectList(wrapper);
        return R.ok(flightDevices);
    }
    @Override
    public R<Page<FlightDevice>> getPage(Page page, FlightDevicePageDto pageDto) {
        LambdaQueryWrapper<FlightDevice> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(pageDto.getDeviceName()),FlightDevice::getDeviceName,pageDto.getDeviceName());
        wrapper.like(StringUtils.isNotBlank(pageDto.getDevicePosition()),FlightDevice::getDevicePosition,pageDto.getDevicePosition());
        wrapper.like(StringUtils.isNotBlank(pageDto.getDeviceCode()),FlightDevice::getDeviceCode,pageDto.getDeviceCode());
        wrapper.like(pageDto.getPositionType() != null,FlightDevice::getPositionType,pageDto.getPositionType());
        wrapper.like(FlightDevice::getDelete,0);
        Page pageResult = this.baseMapper.selectPage(page, wrapper);
        return R.ok(pageResult);
    }
    @Override
    public R updateOne(FlightDevice flightDevice) {
        FlightDevice flightDeviceOne = this.baseMapper.selectById(flightDevice.getId());
       if (StringUtils.equals(flightDevice.getDeviceName(),flightDeviceOne.getDeviceName()) && StringUtils.equals(flightDevice.getDeviceIp(),flightDeviceOne.getDeviceIp()) && StringUtils.equals(flightDevice.getDeviceCode(),flightDeviceOne.getDeviceCode()) && StringUtils.equals(flightDevice.getDevicePosition(),flightDeviceOne.getDevicePosition())){
           LambdaQueryWrapper<FlightDevice> QueryWrapper = new LambdaQueryWrapper<>();
           QueryWrapper.eq(FlightDevice::getDeviceName,flightDevice.getDeviceName());
           QueryWrapper.eq(FlightDevice::getDeviceCode,flightDevice.getDeviceCode());
           QueryWrapper.eq(FlightDevice::getDevicePosition,flightDevice.getDevicePosition());
           QueryWrapper.eq(FlightDevice::getDeviceIp,flightDevice.getDeviceIp());
           QueryWrapper.eq(FlightDevice::getDelete,0);
           Long aLong = this.baseMapper.selectCount(QueryWrapper);
           if (aLong > 0){
               return R.fail("摄像头关联关系重复，不允许更新");
           }
       }
       this.baseMapper.updateById(flightDevice);
       return R.ok("修改成功");
    }

    @Override
    public R delete(FlightDevice flightDevice) {
        FlightDevice flightDeviceOne = this.baseMapper.selectById(flightDevice.getId());
        if (flightDeviceOne == null){
            return R.fail("查询数据有误");
        }
        flightDeviceOne.setDelete(1);
        this.baseMapper.updateById(flightDeviceOne);
        return R.ok("删除成功");
    }

    @Override
    public R add(FlightDevice flightDevice) {
        LambdaQueryWrapper<FlightDevice> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlightDevice::getDeviceName,flightDevice.getDeviceName());
        wrapper.eq(FlightDevice::getDeviceCode,flightDevice.getDeviceCode());
        wrapper.eq(FlightDevice::getDevicePosition,flightDevice.getDevicePosition());
        wrapper.eq(FlightDevice::getDeviceIp,flightDevice.getDeviceIp());
        wrapper.eq(FlightDevice::getDelete,0);
        Long aLong = this.baseMapper.selectCount(wrapper);
        if (aLong > 0){
            return R.fail("摄像头关联关系重复，不允许新增");
        }
        flightDevice.setDelete(0);
        this.baseMapper.insert(flightDevice);
        return R.ok("新增成功");
    }

    @Override
    public Page<FlightDevice> getFlightVideoPage(Page page, FlightDevicePageDto pageDto) {
        Page<FlightDevice> resultPage = this.baseMapper.getFlightVideoPage(page,pageDto);
        try {
            for (FlightDevice record : resultPage.getRecords()) {
                //根据摄像头编码获取对一个的flv播放地址
                String url = getDeviceVideoUrl(record.getDeviceCode());
                if(StringUtils.isBlank(url)){
                    continue;
                }
                url = java.net.URLEncoder.encode(url, "UTF-8");
                record.setFlvUrl(urlAddress+url);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return resultPage;
    }

    public String getDeviceVideoUrl(String deviceCode){
        String sessionKey = redisService.getCacheObject(CacheConstants.FLIGHT_VIDEO_API_SESSION_KEY);
        if(sessionKey == null){
            sessionKey = userLogin();
            if(sessionKey == null){
                return null;
            }
            redisService.setCacheObject(CacheConstants.FLIGHT_VIDEO_API_SESSION_KEY,sessionKey,20L, TimeUnit.MINUTES);
        }

        //获取rtsp地址
        try {
            // 创建URL对象
            URL url = new URL(getVideoUrl);
            // 打开与目标URL的连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            // 设置请求方法为POST
            connection.setRequestMethod("POST");
            // 允许向连接输出数据
            connection.setDoOutput(true);
            // 设置请求属性（请求头）
            connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            connection.setRequestProperty("Cookie", sessionKey);
            // 准备请求体数据
            JSONObject paramJson = new JSONObject();
            paramJson.put("cameraCode",deviceCode);
            JSONObject detailJson = new JSONObject();
            detailJson.put("broadCastType",0);
            detailJson.put("packProtocolType",1);
            detailJson.put("protocolType",2);
            detailJson.put("serviceType",1);
            detailJson.put("streamType",1);
            detailJson.put("transMode",0);
            detailJson.put("clientType",1);
            paramJson.put("mediaURLParam",detailJson);
            // 写入请求体数据
            try (OutputStream os = connection.getOutputStream()) {
                byte[] input = paramJson.toString().getBytes("utf-8");
                os.write(input, 0, input.length);
            }
            // 获取响应代码以触发请求
            int responseCode = connection.getResponseCode();
            System.out.println("响应代码: " + responseCode);

            // 读取响应内容
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String inputLine;
            StringBuilder response = new StringBuilder();
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();
            String resultData = response.toString();
            // 打印响应内容
            System.out.println("响应内容: " + resultData);
            // 断开连接
            connection.disconnect();

            JSONObject dataJson = JSONObject.parseObject(resultData);
            if(!"0".equals(dataJson.getString("resultCode"))){
                return null;
            }
            return dataJson.getString("rtspURL");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("获取rtsp异常: " + e.getMessage());
            return null;
        }
    }

    /**
     * 登录
     * @return
     */
    public String userLogin(){
        String result = null;
        try {
            // 创建URL对象
            URL url = new URL(loginUrl);
            // 打开与目标URL的连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            // 设置请求方法为POST
            connection.setRequestMethod("POST");
            // 允许向连接输出数据
            connection.setDoOutput(true);
            // 设置请求属性（请求头）
            connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            // 准备请求体数据
            String jsonInputString = "{\"userName\": \"" + videoUserName + "\", \"password\": \"" + videoUserPassword + "\"}";
            // 写入请求体数据
            try (OutputStream os = connection.getOutputStream()) {
                byte[] input = jsonInputString.getBytes("utf-8");
                os.write(input, 0, input.length);
            }
            // 获取响应代码以触发请求
            int responseCode = connection.getResponseCode();
            System.out.println("响应代码: " + responseCode);

            Map<String, List<String>> headers = connection.getHeaderFields();
            List<String> cookies = headers.get("Set-Cookie");

            // 打印所有的Set-Cookie信息
            if (cookies != null) {
                for (String cookie : cookies) {
                    System.out.println("Set-Cookie: " + cookie);
                    result = cookie;
                }
            } else {
                System.out.println("响应中未找到Set-Cookie.");
            }
            // 断开连接
            connection.disconnect();
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public FlightDeviceServiceImpl() {
        // 跳过证书验证
        trustAllCertificates();
    }

    /**
     * 信任所有证书
     */
    private void trustAllCertificates() {
        try {
            // 创建一个信任所有证书的TrustManager
            TrustManager[] trustAllCerts = new TrustManager[] {
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {}
                    }
            };

            // 设置SSLContext为使用上述TrustManager
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            // 创建一个HostName验证器，信任所有主机名
            HostnameVerifier allHostsValid = (hostname, session) -> true;
            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}




